package com.formulas.component.catchlog;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.formulas.component.exception.BizException;
import com.formulas.component.exception.SysException;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;

/**
 * @author yiwannuofulasi
 * @date 2023/6/6 14:57
 */
@Aspect
@Order(1)
public class CatchLogAspect {

    private static final Logger logger = LoggerFactory.getLogger(CatchLogAspect.class);

    @Pointcut("@within(CatchAndLog) && execution(public * *(..))")
    public void pointcut() {
    }

    @Around(value = "pointcut()")
    public Object around(ProceedingJoinPoint joinPoint) {
        long startTime = System.currentTimeMillis();
        logRequest(joinPoint);
        Object response = null;
        try {
            response = joinPoint.proceed();
        } catch (Throwable e) {
            response = handleException(joinPoint, e);
        } finally {
            logResponse(startTime, response);
        }
        return response;
    }

    private Object handleException(ProceedingJoinPoint joinPoint, Throwable e) {
        MethodSignature ms = (MethodSignature) joinPoint.getSignature();
        Class returnType = ms.getReturnType();
        if (e instanceof BizException) {
            logger.warn("BizException业务异常 : " + e.getMessage());
            if (logger.isDebugEnabled()) {
                logger.error(e.getMessage(), e);
            }
            Throwable cause = e.getCause();
            String logMessage = null;
            if (null!=cause){
                logMessage = cause.getMessage();
            }
            return ResponseHandlerFactory.get().handle(returnType, ((BizException) e).getErrCode(), e.getMessage()+"_"+logMessage);
        }
        if (e instanceof SysException) {
            logger.error("SysException系统异常 :");
            logger.error(e.getMessage(), e);
            return ResponseHandlerFactory.get().handle(returnType, ((SysException) e).getErrCode(), e.getMessage());
        }
        logger.error("未知异常（未捕获异常） :");
        logger.error(e.getMessage(), e);
        return ResponseHandlerFactory.get().handle(returnType, "未知错误", e.getMessage());
    }

    private void logResponse(long startTime, Object response) {
        try {
            long endTime = System.currentTimeMillis();
            logger.debug("响应内容 : " + JSON.toJSONString(response));
            logger.debug("执行时间 : " + (endTime - startTime) + "ms");
        } catch (Exception e) {
            logger.error("日志响应错误 : " + e);
        }
    }

    private void logRequest(ProceedingJoinPoint joinPoint) {
        try {
            if (!logger.isDebugEnabled()) {
                return;
            }
            logger.debug("开始编译处理: " + joinPoint.getSignature().toShortString());
            Object[] args = joinPoint.getArgs();
            for (Object arg : args) {
                logger.debug("请求内容 : " + JSON.toJSONString(arg, SerializerFeature.IgnoreErrorGetter));
            }
        } catch (Exception e) {
            logger.error("日志请求错误 : " + e);
        }
    }
}
